package ar.edu.unicen.pladema.resources;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * Administra un archivo de configuracion ".properties".
 *  
 * @author Sebastian Perruolo &lt;sperruolo[at]alumnos.exa.unicen.edu.ar&gt;
 */
public final class ConfigMap {
	/** logger. */
	private static Log log = LogFactory.getLog(ConfigMap.class);
	/** Configuración. */
	private Properties properties = null;
	/** Nombre del archivo de configuración. */
	private String file = null;
	/** Determina si la configuración se puede guardar. */
	private boolean readOnly = true;
	
	/**
	 * Creador.
	 * @param propertyfile Archivo del que se levanta la configuración.
	 * @param ro Indica si la configuración se puede guardar.
	 */
	public ConfigMap(final String propertyfile, final boolean ro) {
		this.file = propertyfile;
		this.readOnly = ro;
	}

	/**
	 * Retorna la configuración. Este método permite cargar la configuración
	 * sólo si es utilizada.
	 * 
	 * @return Valores de configuración.
	 */
	private Properties getProperties() {
		if (properties == null) {
			properties = new Properties();
			try {
				InputStream is = JarResourse.getInstance().getResourceStream(file);
				properties.load(is);
			} catch (Exception e) {
				log.error(e, e);
				System.exit(-1);
			}
		}
		return properties;
	}
	
	/**
	 * Retorna el valor en la configuración, para la clave recivida.
	 * @param key Clave de configuración.
	 * @return Valor almacenado bajo la clave.
	 */
	public String getProperty(final String key) {
		return getProperties().getProperty(key);
	}
	/**
	 * Almacena en la configuración, el valor recivido bajo la clave recivida.
	 * @param key Clave de configuración.
	 * @param value Valor a almacenar.
	 */
	public void setProperty(final String key, final String value) {
		getProperties().setProperty(key, value);
	}
	/**
	 * Almacena una lista de valores bajo la clave recivida.
	 * @param key Clave de configuración.
	 * @param values Lista de valores.
	 */
	public void setPropertyList(final String key, final Vector<String> values) {
		int i = 1;
		while (getProperties().remove(key + "." + i) != null) {
			i++;
		}
		
		i = 1;
		for (String value : values) {
			getProperties().setProperty(key + "." + i, value);
			i++;
		}
	}
	/**
	 * Retorna la lista de valores almacenado bajo la clave recivida.
	 * @param key Clave de configuración.
	 * @return Lista de valores.
	 */
	public Vector<String> getPropertyList(final String key) {
		Vector<String> result = new Vector<String>();
		int i = 1;
		String value = getProperty(key + "." + i);
		while (value != null) {
			result.add(value);
			i++;
			value = getProperty(key + "." + i);
		}
		return result;
	}
	
	/**
	 * Almacena la configuración en el archivo.
	 * @param comment Comentario que se mostrará en el archivo.
	 * @throws IOException Si el archivo de configuración no existe o
	 * 		si no se puede guardar.
	 */
	public void save(final String comment) 
			throws IOException {
		if (readOnly) {
			throw new IOException("Config is read-only");
		}
		getProperties().store(new FileOutputStream(file), comment);
		properties = null;
	}
	/**
	 * Retorna una lista de todos los valores de configuración.
	 * @return lista de todos los valores de configuración.
	 */
	public Vector<String> getValues() {
		Vector<String> result = new Vector<String>();
		for (Object o : getProperties().values()) {
			String value = (String) o;
			if (!result.contains(value)) {
				result.add(value);
			}
		}
		return result;
	}
}
